package src.main;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class LogAnalyzer {

    // 更精确的 IPv4 正则表达式
    private static final Pattern IP_PATTERN = Pattern.compile(
            "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}" +
                    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
    );

    public static void main(String[] args) {
        String logPath = "D:\\access.log";
        int topN = 10;

        try {
            List<Map.Entry<String, Long>> topIPs = analyzeTopIPs(logPath, topN);
            printResults(topIPs);
        } catch (IOException e) {
            System.err.println("Error reading log file: " + e.getMessage());
        }
    }

    public static List<Map.Entry<String, Long>> analyzeTopIPs(String filePath, int topN) throws IOException {
        try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
            return lines
                    .map(LogAnalyzer::extractIP)       // 提取 IP 地址
                    .filter(ip -> ip != null)          // 过滤无效行
                    .collect(Collectors.groupingBy(
                            Function.identity(),
                            Collectors.counting()
                    ))
                    .entrySet().stream()
                    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                    .limit(topN)
                    .collect(Collectors.toList());
        }
    }

    private static String extractIP(String logLine) {
        Matcher matcher = IP_PATTERN.matcher(logLine);
        return matcher.find() ? matcher.group() : null;
    }

    private static void printResults(List<Map.Entry<String, Long>> results) {
        System.out.println("Top访问IP统计结果:");
        results.forEach(entry ->
                System.out.printf("IP: %-15s 访问次数: %d%n",
                        entry.getKey(), entry.getValue())
        );
    }
}